#ifndef BANK_SYSTEM_H
#define BANK_SYSTEM_H

#include <vector>
#include <map>
#include <string>
#include <memory> // For std::unique_ptr
#include <random> // For random number generation

// Forward declarations
namespace MiniBanking
{
    class Customer;
    class BankAccount;
    class SavingsAccount;
    class CheckingAccount;
    class Transaction;
    enum class TransactionType; // Forward declare enum class
}

namespace MiniBanking
{

    /**
     * @brief Manages the entire banking system operations.
     *
     * Handles customer creation, account management, transactions,
     * user interface interaction, and report generation coordination.
     */
    class BankSystem
    {
    private:
        std::map<std::string, Customer> customers_;                    // Map Customer Name -> Customer Object
        std::map<std::string, std::unique_ptr<BankAccount>> accounts_; // Map Account ID -> Account Object Pointer
        std::vector<Transaction> transactions_;                        // List of all transactions

        // For unique ID generation
        std::mt19937 randomEngine_;                 // Random number generator
        unsigned int nextTransactionIDCounter_ = 1; // Simple counter for transaction IDs

        // --- Private Helper Methods ---

        // UI Helpers
        void displayMainMenu() const;
        void displayCustomerMenu(const Customer &customer) const;
        void displayAccountMenu(const BankAccount &account) const;
        void clearScreen() const; // Placeholder
        void pause() const;       // Placeholder
        std::string promptForString(const std::string &prompt) const;
        double promptForDouble(const std::string &prompt) const;
        int promptForInt(const std::string &prompt, int minVal, int maxVal) const;

        // Core Logic Helpers
        Customer *findCustomerByName(const std::string &name);             // Returns mutable pointer
        const Customer *findCustomerByName(const std::string &name) const; // Const overload
        BankAccount *findAccountByID(const std::string &id);               // Returns raw pointer to managed object
        const BankAccount *findAccountByID(const std::string &id) const;   // Const overload

        std::string generateUniqueAccountID(bool isSavings);
        std::string generateUniqueTransactionID();
        void addTransaction(TransactionType type, double amount,
                            const std::string &sourceID, const std::string &destID, const std::string &note);

        // Menu Action Handlers
        void handleRegisterNewCustomer();
        void handleAccessCustomerAccounts();
        void handleDisplayAllAccounts() const;
        void handleGenerateGlobalReport() const;

        // Sub-Menu Action Handlers (called from access customer/account)
        void handleAccessSpecificAccount(Customer &customer, bool accessSavings);
        void handleViewCustomerTransactions(const Customer &customer) const;
        void handleGenerateCustomerReport(const Customer &customer) const;

        void handleDeposit(BankAccount *account);
        void handleWithdraw(BankAccount *account);
        void handleTransfer(BankAccount *sourceAccount);
        void handleViewAccountHistory(const BankAccount &account) const;
        void handleGenerateAccountReport(const BankAccount &account) const;

    public:
        /**
         * @brief Constructs the BankSystem, initializing the random engine.
         */
        BankSystem();

        /**
         * @brief Runs the main application loop.
         */
        void run();

        // Destructor needed? Default should be okay thanks to smart pointers and standard containers.
        ~BankSystem() = default;

        // Delete copy/move operations as BankSystem is likely a singleton logical entity
        BankSystem(const BankSystem &) = delete;
        BankSystem &operator=(const BankSystem &) = delete;
        BankSystem(BankSystem &&) = delete;
        BankSystem &operator=(BankSystem &&) = delete;
    };

} // namespace MiniBanking

#endif // BANK_SYSTEM_H
